package com.market.plus.ocm.service;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.market.plus.core.domain.Album;
import com.market.plus.core.domain.Avatar;
import com.market.plus.core.domain.ContentFile;
import com.market.plus.core.domain.News;
import com.market.plus.core.domain.Participant;
import com.market.plus.core.domain.Tribe;
import com.market.plus.core.domain.UserInfo;
import com.market.plus.core.dto.AlbumDto;
import com.market.plus.core.dto.CommentDto;
import com.market.plus.core.dto.ContentFileDto;
import com.market.plus.core.dto.ParticipantDto;
import com.market.plus.core.dto.TribeDto;
import com.market.plus.core.exception.OCMRuntimeException;
import com.market.plus.core.model.ImageSizeType;
import com.market.plus.core.model.MetadataFile;
import com.market.plus.core.model.MultipartFile;
import com.market.plus.core.model.Picture;
import com.market.plus.core.service.MarketOCMService;
import com.market.plus.core.util.MarketUtil;
import com.market.plus.local.ocm.util.LocalOCMUtil;
import com.market.plus.ocm.model.MetadataScaleFile;
import com.ocm.core.constant.OCMConstant;
import com.ocm.core.domain.PropertyDefinition;
import com.ocm.core.dto.SecurityDto;
import com.ocm.core.dto.StorageDto;
import com.ocm.core.dto.UserInfoDto;
import com.ocm.core.model.ClassInstance;
import com.ocm.core.model.Files;
import com.ocm.core.model.ReferenceValue;
import com.ocm.core.service.ContentEngineService;
import com.opm.security.core.model.ExternalUserDetails;

@Service("marketOCMService")
public class MarketOCMServiceImpl implements MarketOCMService {

   private ContentEngineService contentEngineService;

   private ScaleImageService scaleImageService;

   private MarketOCMSecurityService securityService;

   @Autowired
   public MarketOCMServiceImpl(@Qualifier("localContentEngineService") ContentEngineService contentEngineService,
         @Qualifier("scaleImageService") ScaleImageService scaleImageService,
         @Qualifier("marketOCMSecurityService") MarketOCMSecurityService securityService) {
      this.contentEngineService = contentEngineService;
      this.scaleImageService = scaleImageService;
      this.securityService = securityService;
   }

   public MetadataFile getFile(String fileGUID, ImageSizeType imageSizeType) {
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      MetadataFile metadataFile = null;
      ClassInstance classInstance = null;
      switch (imageSizeType) {
      case SMALL:
         classInstance = (ClassInstance) this.contentEngineService
               .downloadFromReferenceValues(fileGUID, MarketOCMConstant.PROPERTY_MARKETDOCUMENT_SCALESMALLIMAGE,
                     new String[] { MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP,
                           MarketOCMConstant.PROPERTY_MARKETDOCUMENT_WIDTH,
                           MarketOCMConstant.PROPERTY_MARKETDOCUMENT_HEIGHT }, 0, storage);
         break;
      case MEDIUM:
         classInstance = (ClassInstance) this.contentEngineService
               .downloadFromReferenceValues(fileGUID, MarketOCMConstant.PROPERTY_MARKETDOCUMENT_SCALEIMAGE,
                     new String[] { MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP,
                           MarketOCMConstant.PROPERTY_MARKETDOCUMENT_WIDTH,
                           MarketOCMConstant.PROPERTY_MARKETDOCUMENT_HEIGHT }, 0, storage);
         break;
      case REAL:
         Files file = this.contentEngineService.download(fileGUID, MarketOCMConstant.MARKETSTORAGE,
               new String[] { MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP });
         if (file.getLength() > 0) {
            metadataFile = new MetadataFile();
            metadataFile.setFilename(file.getFilename());
            metadataFile.setInputStream(file.getInputStream());
            metadataFile.setLength(file.getLength());
            metadataFile.setType(file.getType());
            metadataFile.setTooltip(file.getTooltip());
         }
         break;
      default:
         break;
      }
      if (classInstance != null) {
         metadataFile = new MetadataFile();
         metadataFile.setGuid(classInstance.getNodeUUID());
         Map<PropertyDefinition, Object> propertiesMap = classInstance.getProperties();
         for (Iterator<PropertyDefinition> it = propertiesMap.keySet().iterator(); it.hasNext();) {
            PropertyDefinition propertyDefinition = it.next();
            String propertyName = propertyDefinition.getName();
            Object value = propertiesMap.get(propertyDefinition);
            if (OCMConstant.CONTENT_DATA.equalsIgnoreCase(propertyName)) {
               metadataFile.setInputStream(value == null ? null : (InputStream) value);
            } else if (OCMConstant.FILE_NAME.equalsIgnoreCase(propertyName)) {
               metadataFile.setFilename(value == null ? "" : value.toString());
            } else if (OCMConstant.CONTENT_TYPE.equalsIgnoreCase(propertyName)) {
               metadataFile.setType(value == null ? "" : value.toString());
            } else if (OCMConstant.CONTENT_LENGTH.equalsIgnoreCase(propertyName)) {
               metadataFile.setLength(value == null ? 0 : Integer.parseInt(value.toString()));
            } else if (MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP.equalsIgnoreCase(propertyName)) {
               metadataFile.setTooltip(value == null ? "" : value.toString());
            } else if (MarketOCMConstant.PROPERTY_MARKETDOCUMENT_HEIGHT.equalsIgnoreCase(propertyName)) {
               metadataFile.setHeight(value == null ? 0 : Integer.parseInt(value.toString()));
            } else if (MarketOCMConstant.PROPERTY_MARKETDOCUMENT_WIDTH.equalsIgnoreCase(propertyName)) {
               metadataFile.setWidth(value == null ? 0 : Integer.parseInt(value.toString()));
            }
         }
      }
      return metadataFile;
   }

   @SuppressWarnings("unchecked")
   public List<AlbumDto> getAlbums(String participantGUID) {
      List<AlbumDto> albumDtos = new ArrayList<AlbumDto>();
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      List<ClassInstance> classInstances = (List<ClassInstance>) this.contentEngineService.fetchReferenceValues(
            participantGUID, MarketOCMConstant.PROPERTY_PARTICIPANT_ALBUMS, new String[] { MarketOCMConstant.PROPERTY_ALBUM_NAME },MarketOCMConstant.MAX_ITEMS_ALBUMS, storage);
      List<ContentFileDto> contentFiles = null;
      for (int index = 0; index < classInstances.size(); index++) {
         contentFiles = new ArrayList<ContentFileDto>();
         ClassInstance classInstance = classInstances.get(index);
         String albumName = LocalOCMUtil.getPropertyValue(MarketOCMConstant.PROPERTY_ALBUM_NAME, classInstance.getProperties()).toString();
         AlbumDto album = new AlbumDto();
         album.setName(albumName);
         album.setAlbumGUID(classInstance.getNodeUUID());
         List<ClassInstance> pictiures = (List<ClassInstance>) this.contentEngineService.fetchReferenceValues(
               album.getAlbumGUID(), MarketOCMConstant.PROPERTY_ALBUM_DOCUMENTS, new String[] { MarketOCMConstant.PROPERTY_MARKETDOCUMENT_DOCUMENTTITLE }, MarketOCMConstant.MAX_ITEMS_ALBUM_PICTURE,
               storage);
         for (int indexPic = 0; indexPic < pictiures.size(); indexPic++) {
            ClassInstance picture = pictiures.get(indexPic);
            ContentFileDto contentFileDto = new ContentFileDto();
            contentFileDto.setGuid(picture.getNodeUUID());
            contentFiles.add(contentFileDto);
         }
         album.setContentFiles(contentFiles);
         albumDtos.add(album);
      }
      return albumDtos;
   }

   @Transactional(value = "ocmTransactionManager", readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
   public String addParticipant(Participant participant, CommonsMultipartFile avatarFile, String username,
         String password) throws Exception {
      String avatarGUID = null;
      String albumGUID = null;
      String participantGUID = null;
      String scaleImageGUID = null;
      String scaleSmallImageGUID = null;
      boolean hasUploaded = (avatarFile != null && avatarFile.getSize() > 0);
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      try {
         Long userId = this.contentEngineService.addNewUser(username, password, new String[] { MarketOCMConstant.ROLE_SOCICAL_PUBLIC });
         UserInfo userInfo = participant.getUserInfo();
         userInfo.setExternalId(userId.toString());
         userInfo.setParticipant(participant);

         if (hasUploaded) {
            List<SecurityDto> securityDtos = this.securityService.getAvatar(userId);
            MetadataScaleFile metadataScaleFiles[] = this.scaleImageService.scaleMediumAndSmall(avatarFile);
            Map<String, Object> scaleValues = getScaleFileValues(metadataScaleFiles[0]);
            scaleImageGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_SCALEIMAGE, scaleValues, storage,
                  securityDtos);

            scaleValues = getScaleFileValues(metadataScaleFiles[1]);
            scaleSmallImageGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_SCALESMALLIMAGE, scaleValues, storage,
                  securityDtos);

            ReferenceValue referenceValue = ReferenceValue.getInstance();
            referenceValue.addUUID(scaleImageGUID);

            ReferenceValue referenceSmallValue = ReferenceValue.getInstance();
            referenceSmallValue.addUUID(scaleSmallImageGUID);

            Map<String, Object> avatarValues = getFileValues(avatarFile);
            avatarValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP, "");
            avatarValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_SCALEIMAGE, referenceValue);
            avatarValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_SCALESMALLIMAGE, referenceSmallValue);

            avatarGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_MARKETDOCUMENT, avatarValues, storage,
                  securityDtos);
         }
         if (avatarGUID != null) {
            ContentFile contentFile = getContentFile(avatarGUID, avatarFile);
            participant.addContentFile(contentFile);
            Avatar avatar = new Avatar();
            avatar.setContentFile(contentFile);
            participant.setAvatar(avatar);
         }
         Album album = participant.getAlbums().get(0);
         Map<String, Object> albumValues = new HashMap<String, Object>();
         albumValues.put(MarketOCMConstant.PROPERTY_ALBUM_NAME, album.getName());
         if (avatarGUID != null) {
            ReferenceValue referenceValue = ReferenceValue.getInstance();
            referenceValue.addUUID(avatarGUID);
            albumValues.put(MarketOCMConstant.PROPERTY_ALBUM_DOCUMENTS, referenceValue);
         }
         albumGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_ALBUM, albumValues, storage,
               this.securityService.getAlbum(userId));
         album.setAlbumGUID(albumGUID);

         Map<String, Object> participantValues = new HashMap<String, Object>();
         participantValues.put(MarketOCMConstant.PROPERTY_PARTICIPANT_LASTNAME, participant.getLastName());
         participantValues.put(MarketOCMConstant.PROPERTY_PARTICIPANT_FIRSTNAME, participant.getFirstName());
         ReferenceValue referenceValue = ReferenceValue.getInstance();
         referenceValue.addUUID(albumGUID);
         participantValues.put(MarketOCMConstant.PROPERTY_PARTICIPANT_ALBUMS, referenceValue);
         participantGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_PARTICIPANT, participantValues, storage,
               this.securityService.getParticipant(userId));
         participant.setGuid(participantGUID);
      } catch (Exception exception) {
         if (scaleSmallImageGUID != null)
            this.contentEngineService.delete(storage, scaleSmallImageGUID);

         if (scaleImageGUID != null)
            this.contentEngineService.delete(storage, scaleImageGUID);

         if (avatarGUID != null)
            this.contentEngineService.delete(storage, avatarGUID);

         if (albumGUID != null)
            this.contentEngineService.delete(storage, albumGUID);

         if (participantGUID != null)
            this.contentEngineService.delete(storage, participantGUID);
         throw new OCMRuntimeException(exception);
      }
      return participantGUID;
   }

   @SuppressWarnings("unchecked")
   public List<Picture> getPictures(String albumUUID) {
      List<Picture> pictures = new ArrayList<Picture>();
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      List<ClassInstance> classes = (List<ClassInstance>) this.contentEngineService.fetchReferenceValues(albumUUID,
            MarketOCMConstant.PROPERTY_ALBUM_DOCUMENTS, new String[] { MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP }, MarketOCMConstant.MAX_ITEMS_DETAIL_ALBUM_PICTURES, storage);
      for (int indexPic = 0; indexPic < classes.size(); indexPic++) {
         ClassInstance classInstance = classes.get(indexPic);
         Picture picture = new Picture();
         picture.setUUID(classInstance.getNodeUUID());
         Object tooltip = LocalOCMUtil.getPropertyValue(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP, classInstance.getProperties());
         picture.setComment(tooltip == null ? "" : tooltip.toString());
         pictures.add(picture);
      }
      return pictures;
   }

   @Transactional(value = "ocmTransactionManager", readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
   public String addFiles(String albumUUID, MultipartFile multipartFile) throws Exception {
      String scaleImageGUID = null;
      String scaleSmallImageGUID = null;
      String documentGUID = null;
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      try {
         List<SecurityDto> securityDtos = this.securityService.getImage();

         MetadataScaleFile metadataScaleFiles[] = this.scaleImageService.scaleMediumAndSmall(multipartFile.getFile());
         Map<String, Object> scaleValues = getScaleFileValues(metadataScaleFiles[0]);
         scaleImageGUID = this.contentEngineService
               .createInstance(MarketOCMConstant.CLASS_SCALEIMAGE, scaleValues, storage, securityDtos);

         scaleValues = getScaleFileValues(metadataScaleFiles[1]);
         scaleSmallImageGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_SCALESMALLIMAGE, scaleValues, storage,
               securityDtos);

         ReferenceValue referenceValue = ReferenceValue.getInstance();
         referenceValue.addUUID(scaleImageGUID);

         ReferenceValue referenceSmallValue = ReferenceValue.getInstance();
         referenceSmallValue.addUUID(scaleSmallImageGUID);

         Map<String, Object> documentValues = getFileValues(multipartFile.getFile());
         documentValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP, multipartFile.getTooltip());
         documentValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_SCALEIMAGE, referenceValue);
         documentValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_SCALESMALLIMAGE, referenceSmallValue);
         documentGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_MARKETDOCUMENT, documentValues, storage,
               securityDtos);
         Map<String, Object> albumValues = new HashMap<String, Object>();
         referenceValue = ReferenceValue.getInstance();
         referenceValue.addUUID(documentGUID);
         albumValues.put(MarketOCMConstant.PROPERTY_ALBUM_DOCUMENTS, referenceValue);
         this.contentEngineService.updateInstance(albumUUID, albumValues, storage);
      } catch (Exception exception) {
         if (scaleImageGUID != null)
            this.contentEngineService.delete(storage, scaleImageGUID);

         if (scaleSmallImageGUID != null)
            this.contentEngineService.delete(storage, scaleSmallImageGUID);

         if (documentGUID != null)
            this.contentEngineService.delete(storage, documentGUID);
         throw new OCMRuntimeException(exception);
      }
      return documentGUID;
   }

   @Transactional(value = "ocmTransactionManager", readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
   public String addAlbum(Participant participant, Album album) throws Exception {
      String albumGUID = null;
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      try {
         Map<String, Object> albumValues = new HashMap<String, Object>();
         albumValues.put(MarketOCMConstant.PROPERTY_ALBUM_NAME, album.getName());
         albumGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_ALBUM, albumValues, storage,
               this.securityService.getAlbum());
         Map<String, Object> participantValues = new HashMap<String, Object>();
         ReferenceValue referenceValue = ReferenceValue.getInstance();
         referenceValue.addUUID(albumGUID);
         participantValues.put(MarketOCMConstant.PROPERTY_PARTICIPANT_ALBUMS, referenceValue);
         this.contentEngineService.updateInstance(participant.getGuid(), participantValues, storage);
      } catch (Exception exception) {
         if (albumGUID != null)
            this.contentEngineService.delete(storage, albumGUID);
         throw new OCMRuntimeException(exception);
      }
      return albumGUID;
   }

   @Transactional(value = "ocmTransactionManager", readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
   public String saveNews(Participant participant, News news, long[] myFriendIds) throws Exception {
      String newGUID = news.getGuid();
      boolean hasNew = false;
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      try {
         Map<String, Object> newsValues = new HashMap<String, Object>();
         newsValues.put(MarketOCMConstant.PROPERTY_NEWS_CONTENT, news.getContent());
         newsValues.put(MarketOCMConstant.PROPERTY_NEWS_TITLE, news.getTitle());
         if (MarketUtil.hasEmptyOrNull(newGUID)) {
            hasNew = true;
            newGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_NEWS, newsValues, storage,
                  this.securityService.getNew(myFriendIds));

            Map<String, Object> participantValues = new HashMap<String, Object>();
            ReferenceValue referenceValue = ReferenceValue.getInstance();
            referenceValue.addUUID(newGUID);
            participantValues.put(MarketOCMConstant.PROPERTY_PARTICIPANT_NEWS, referenceValue);
            this.contentEngineService.updateInstance(participant.getGuid(), participantValues, storage);
         } else {
            this.contentEngineService.updateInstance(newGUID, newsValues, storage);
         }

      } catch (Exception exception) {
         if (hasNew && (newGUID != null))
            this.contentEngineService.delete(storage, newGUID);

         throw new OCMRuntimeException(exception);
      }
      return newGUID;
   }

   @Transactional(value = "ocmTransactionManager", readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
   public String addTribe(Participant participant, Tribe tribe, Album album, CommonsMultipartFile file)
         throws Exception {
      String avatarGUID = null;
      String scaleAvatarGUID = null;
      String scaleSmallavatarGUID = null;
      String tribeAlbumGUID = album.getAlbumGUID();
      String tribeGUID = null;
      String tribeNewsGUID = null;
      ContentFile contentFile = null;
      boolean hasAddAlbum = false;
      boolean hasUploaded = (file != null && file.getSize() > 0);
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      try {
         if (hasUploaded) {
            List<SecurityDto> securityDtos = this.securityService.getImage();

            MetadataScaleFile metadataScaleFiles[] = this.scaleImageService.scaleMediumAndSmall(file);
            Map<String, Object> scaleValues = getScaleFileValues(metadataScaleFiles[0]);
            scaleAvatarGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_SCALEIMAGE, scaleValues, storage,
                  securityDtos);

            scaleValues = getScaleFileValues(metadataScaleFiles[1]);
            scaleSmallavatarGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_SCALESMALLIMAGE, scaleValues,
                  storage, securityDtos);

            ReferenceValue referenceValue = ReferenceValue.getInstance();
            referenceValue.addUUID(scaleAvatarGUID);

            ReferenceValue referenceSmallValue = ReferenceValue.getInstance();
            referenceSmallValue.addUUID(scaleSmallavatarGUID);

            Map<String, Object> avatarValues = getFileValues(file);
            avatarValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_TOOLTIP, "");
            avatarValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_SCALEIMAGE, referenceValue);
            avatarValues.put(MarketOCMConstant.PROPERTY_MARKETDOCUMENT_SCALESMALLIMAGE, referenceSmallValue);

            avatarGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_MARKETDOCUMENT, avatarValues, storage,
                  securityDtos);
            contentFile = getContentFile(avatarGUID, file);
            Avatar avatar = new Avatar();
            avatar.setContentFile(contentFile);
            tribe.setAvatar(avatar);
         }
         if (tribeAlbumGUID == null) {
            hasAddAlbum = true;
            Map<String, Object> albumValues = new HashMap<String, Object>();
            if (avatarGUID != null) {
               ReferenceValue referenceValue = ReferenceValue.getInstance();
               referenceValue.addUUID(avatarGUID);
               albumValues.put(MarketOCMConstant.PROPERTY_ALBUM_DOCUMENTS, referenceValue);
            }
            tribeAlbumGUID = addAlbum(participant, album, storage, albumValues);
            album.setAlbumGUID(tribeAlbumGUID);
         } else {
            if (hasUploaded) {
               MultipartFile multipartFile = new MultipartFile();
               multipartFile.setFile(file);
               multipartFile.setTooltip("");
               addFiles(tribeAlbumGUID, multipartFile);
            }
         }

         News news = tribe.getNews().get(0);
         if (contentFile != null) {
            news.addContentFile(contentFile);
         }
         tribeNewsGUID = addTribeNews(storage, news);
         news.setGuid(tribeNewsGUID);

         ReferenceValue referenceValue = ReferenceValue.getInstance();
         referenceValue.addUUID(tribeNewsGUID);

         Map<String, Object> tribeValues = new HashMap<String, Object>();
         tribeValues.put(MarketOCMConstant.PROPERTY_TRIBE_NAME, tribe.getName());
         tribeValues.put(MarketOCMConstant.PROPERTY_TRIBE_DESCRIPTION, tribe.getDescription());
         tribeValues.put(MarketOCMConstant.PROPERTY_TRIBE_NEWS, referenceValue);
         tribeGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_TRIBE, tribeValues, storage,
               this.securityService.getTribe(null, false));

         Map<String, Object> participantValues = new HashMap<String, Object>();
         referenceValue = ReferenceValue.getInstance();
         referenceValue.addUUID(tribeGUID);
         participantValues.put(MarketOCMConstant.PROPERTY_PARTICIPANT_TRIBES, referenceValue);
         this.contentEngineService.updateInstance(participant.getGuid(), participantValues, storage);
      } catch (Exception exception) {
         if (scaleAvatarGUID != null)
            this.contentEngineService.delete(storage, scaleAvatarGUID);

         if (scaleSmallavatarGUID != null)
            this.contentEngineService.delete(storage, scaleSmallavatarGUID);

         if (avatarGUID != null)
            this.contentEngineService.delete(storage, avatarGUID);

         if (hasAddAlbum && (tribeAlbumGUID != null))
            this.contentEngineService.delete(storage, tribeAlbumGUID);

         if (tribeNewsGUID != null)
            this.contentEngineService.delete(storage, tribeNewsGUID);

         if (tribeGUID != null)
            this.contentEngineService.delete(storage, tribeGUID);

         throw new OCMRuntimeException(exception);
      }
      return tribeGUID;
   }

   @SuppressWarnings("unchecked")
   public List<TribeDto> getTribes(String participantGUID) {
      List<TribeDto> tribeDtos = new ArrayList<TribeDto>();
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      List<ClassInstance> classInstances = (List<ClassInstance>) this.contentEngineService.fetchReferenceValues(
            participantGUID, MarketOCMConstant.PROPERTY_PARTICIPANT_TRIBES, new String[] { MarketOCMConstant.PROPERTY_TRIBE_NAME },MarketOCMConstant.MAX_ITEMS_TRIBES, storage);
      for (int index = 0; index < classInstances.size(); index++) {
         ClassInstance classInstance = classInstances.get(index);
         String tribeName = LocalOCMUtil.getPropertyValue(MarketOCMConstant.PROPERTY_TRIBE_NAME, classInstance.getProperties()).toString();
         TribeDto tribe = new TribeDto();
         tribe.setName(tribeName);
         tribe.setTribeGUID(classInstance.getNodeUUID());
         tribeDtos.add(tribe);
      }
      return tribeDtos;
   }

   @SuppressWarnings("unchecked")
   public String[] getNewGUIDs(String participantGUID) {
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      List<ClassInstance> classInstances = (List<ClassInstance>) this.contentEngineService.fetchReferenceValues(
            participantGUID, MarketOCMConstant.PROPERTY_PARTICIPANT_NEWS , null, 0, storage);
      String[] newsDtos = new String[] {};
      if (classInstances != null) {
         newsDtos = new String[classInstances.size()];
         for (int index = 0; index < classInstances.size(); index++) {
            ClassInstance classInstance = classInstances.get(index);
            newsDtos[index] = classInstance.getNodeUUID();
         }
      }
      return newsDtos;
   }

   @SuppressWarnings("unchecked")
   public String[] getTribeNewGUIDs(String tribeGUID) {
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      List<ClassInstance> classInstances = (List<ClassInstance>) this.contentEngineService.fetchReferenceValues(
            tribeGUID, MarketOCMConstant.PROPERTY_TRIBE_NEWS, null, 0, storage);
      String[] newsDtos = new String[classInstances.size()];
      for (int index = 0; index < classInstances.size(); index++) {
         ClassInstance classInstance = classInstances.get(index);
         newsDtos[index] = classInstance.getNodeUUID();
      }
      return newsDtos;
   }

   @Transactional(value = "ocmTransactionManager", readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
   public String comments(String newsGUID, CommentDto comment) throws Exception {
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      String commentGUID = null;
      try {
         UserInfoDto userCreator = this.contentEngineService.getContentCreator(storage, newsGUID);
         Map<String, Object> commentValues = new HashMap<String, Object>();
         commentValues.put(MarketOCMConstant.PROPERTY_COMMENT_CONTENT, comment.getContent());
         commentValues.put(MarketOCMConstant.PROPERTY_COMMENT_USER, comment.getParticipant().getGuid());
         commentGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_COMMENT, commentValues, storage,
               this.securityService.getComment(userCreator));

         Map<String, Object> newValues = new HashMap<String, Object>();
         ReferenceValue referenceValue = ReferenceValue.getInstance();
         referenceValue.addUUID(commentGUID);
         newValues.put(MarketOCMConstant.PROPERTY_NEWS_COMMENTS, referenceValue);
         this.contentEngineService.updateInstance(newsGUID, newValues, storage);
      } catch (Exception exception) {
         if (commentGUID != null)
            this.contentEngineService.delete(storage, commentGUID);
         throw new OCMRuntimeException(exception);
      }
      return commentGUID;
   }

   @SuppressWarnings("unchecked")
   public List<CommentDto> getComment(String newsGUID) {
      StorageDto storage = this.contentEngineService.getStorage(MarketOCMConstant.MARKETSTORAGE);
      List<ClassInstance> classInstances = (List<ClassInstance>) this.contentEngineService.fetchReferenceValues(
            newsGUID, MarketOCMConstant.PROPERTY_NEWS_COMMENTS, new String[] { MarketOCMConstant.PROPERTY_COMMENT_CONTENT, MarketOCMConstant.PROPERTY_COMMENT_USER}, 0, storage);
      List<CommentDto> commentDtos = new ArrayList<CommentDto>();
      for (int index = 0; index < classInstances.size(); index++) {
         ClassInstance classInstance = classInstances.get(index);

         String userComment = LocalOCMUtil.getPropertyValue(MarketOCMConstant.PROPERTY_COMMENT_USER, classInstance.getProperties()).toString();
         ParticipantDto participantDto = new ParticipantDto();
         participantDto.setGuid(userComment);

         String content = LocalOCMUtil.getPropertyValue(MarketOCMConstant.PROPERTY_COMMENT_CONTENT, classInstance.getProperties()).toString();

         CommentDto commentDto = new CommentDto();
         commentDto.setContent(content);
         commentDto.setParticipantDto(participantDto);
         commentDtos.add(commentDtos.size(), commentDto);
      }
      return commentDtos;
   }

   private String addTribeNews(StorageDto storage, News news) throws Exception {
      Map<String, Object> newsValues = new HashMap<String, Object>();
      newsValues.put(MarketOCMConstant.PROPERTY_NEWS_CONTENT, news.getContent());
      newsValues.put(MarketOCMConstant.PROPERTY_NEWS_TITLE, news.getTitle());
      String newGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_TRIBE_NEWS, newsValues, storage,
            this.securityService.getTribe(null, false));
      return newGUID;
   }

   private String addAlbum(Participant participant, Album album, StorageDto storage, Map<String, Object> albumValues)
         throws Exception {
      if (albumValues == null)
         albumValues = new HashMap<String, Object>();

      if (!albumValues.containsKey(MarketOCMConstant.PROPERTY_ALBUM_NAME))
         albumValues.put(MarketOCMConstant.PROPERTY_ALBUM_NAME, album.getName());

      String albumGUID = this.contentEngineService.createInstance(MarketOCMConstant.CLASS_ALBUM, albumValues, storage,
            this.securityService.getAlbum());
      Map<String, Object> participantValues = new HashMap<String, Object>();
      ReferenceValue referenceValue = ReferenceValue.getInstance();
      referenceValue.addUUID(albumGUID);
      participantValues.put(MarketOCMConstant.PROPERTY_PARTICIPANT_ALBUMS, referenceValue);
      this.contentEngineService.updateInstance(participant.getGuid(), participantValues, storage);
      return albumGUID;
   }

   private Map<String, Object> getFileValues(CommonsMultipartFile file) throws IOException {
      Map<String, Object> fileValues = new HashMap<String, Object>();
      fileValues.put(OCMConstant.DOCUMENT_TITLE, file.getOriginalFilename());
      fileValues.put(OCMConstant.CONTENT_TYPE, file.getContentType());
      fileValues.put(OCMConstant.CONTENT_LENGTH, file.getSize());
      fileValues.put(OCMConstant.FILE_NAME, file.getOriginalFilename());
      fileValues.put(OCMConstant.CONTENT_DATA, file.getInputStream());
      return fileValues;
   }

   private Map<String, Object> getScaleFileValues(MetadataScaleFile file) throws IOException {
      Map<String, Object> fileValues = new HashMap<String, Object>();
      fileValues.put(OCMConstant.DOCUMENT_TITLE, file.getOriginalFile().getOriginalFilename());
      fileValues.put(OCMConstant.CONTENT_TYPE, file.getOriginalFile().getContentType());
      fileValues.put(OCMConstant.CONTENT_LENGTH, file.getSize());
      fileValues.put(OCMConstant.FILE_NAME, file.getOriginalFile().getOriginalFilename());
      fileValues.put(OCMConstant.CONTENT_DATA, file.getInputStream());
      fileValues.put("width", file.getWidth());
      fileValues.put("height", file.getHeight());
      return fileValues;
   }

   private ContentFile getContentFile(String guid, CommonsMultipartFile file) throws IOException {
      ContentFile contentFile = new ContentFile();
      contentFile.setGuid(guid);
      contentFile.setFileName(file.getOriginalFilename());
      contentFile.setLengthFile(file.getSize());
      contentFile.setMineType(file.getContentType());
      return contentFile;
   }

   public ExternalUserDetails loadUserByUsername(String username) {
      ExternalUserDetails userDetails = this.contentEngineService.loadByUsername(username);
      return userDetails;
   }
}
